package com.jiubanqingchen.wish.framework.base.service;

import cn.hutool.core.annotation.AnnotationUtil;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.*;
import com.jiubanqingchen.wish.framework.annotation.HideColumn;
import com.jiubanqingchen.wish.framework.annotation.ShowColumn;
import com.jiubanqingchen.wish.framework.annotation.SqlKey;
import com.jiubanqingchen.wish.framework.exception.WishException;
import com.jiubanqingchen.wish.framework.exception.WishExceptionKey;
import com.jiubanqingchen.wish.kit.AopKit;
import com.jiubanqingchen.wish.kit.BlankKit;
import com.jiubanqingchen.wish.kit.RecordKit;
import com.jiubanqingchen.wish.kit.SqlKit;

import java.util.List;

/**
 * @author light_dust
 * @since 2020/12/20 10:40
 */
public class BaseService implements IBaseService {
    @Override
    public List<Record> list(String dataSource, Kv kv) throws WishException {
        return this.list(dataSource, getSqlKey(), kv);
    }

    @Override
    public List<Record> list(String dataSource, String sqlKey, Kv kv) throws WishException {
        List<Record> recordList = getSqlTemplate(dataSource, sqlKey, kv).find();
        if (BlankKit.isBlankList(recordList)) return recordList;
        recordList.forEach(record -> setExtend(record, kv));
        return recordList;
    }

    @Override
    public Record id(String dataSource, String id, Kv kv) throws WishException {
        return this.id(dataSource, getSqlKey(), id, kv);
    }

    @Override
    public Record id(String dataSource, String sqlKey, String id, Kv kv) throws WishException {
        Record record = getSqlTemplate(dataSource, sqlKey, kv).findFirst();
        if (record != null) setExtend(record, kv);
        return record;
    }

    @Override
    public Page<Record> page(String dataSource, int pageNum, int limit, Kv kv) throws WishException {
        return this.page(dataSource, getSqlKey(), pageNum, limit, kv);
    }

    @Override
    public Page<Record> page(String dataSource, String sqlKey, int pageNum, int limit, Kv kv) throws WishException {
        //得到page对象
        Page<Record> page = getSqlTemplate(dataSource, sqlKey, kv).paginate(pageNum, limit);
        SqlKit.orderHandle(kv);
        List<Record> recordList = page.getList();
        if (BlankKit.isBlankList(recordList)) return page;
        recordList.forEach(record -> setExtend(record, kv));
        return page;
    }

    @Override
    public DbTemplate getSqlTemplate(String dataSource, String sqlKey, Kv kv) throws WishException {
        if (kv == null) kv = Kv.create();
        DbTemplate dbTemplate = wishDb(dataSource).template(sqlKey, kv);
        if (dbTemplate.getSqlPara() == null) throw new WishException(WishExceptionKey.SQL_ERROR);
        return dbTemplate;
    }

    @Override
    public String getHideColumns() {
        return AnnotationUtil.getAnnotationValue(AopKit.me().getUsefulClass(getClass()), HideColumn.class);
    }

    @Override
    public String getShowColumns() {
        return AnnotationUtil.getAnnotationValue(AopKit.me().getUsefulClass(getClass()), ShowColumn.class);
    }

    /**
     * 多数据源获取
     *
     * @param configName 配置的数据源名称
     */
    public DbPro wishDb(String configName) {
        return StrKit.isBlank(configName) ? Db.use() : Db.use(configName);
    }

    /**
     * 获取service的sqlKey
     */
    public String getSqlKey() throws WishException {
        String sqlKey = AnnotationUtil.getAnnotationValue(AopKit.me().getUsefulClass(getClass()), SqlKey.class);
        if (StrKit.isBlank(sqlKey)) throw new WishException(WishExceptionKey.SQL_ERROR);
        return sqlKey;
    }

    /**
     * 设置扩展
     *
     * @param record record记录
     * @param kv     参数
     */
    private void setExtend(Record record, Kv kv) {
        if (kv == null) kv = Kv.create();
        //设置显示列与隐藏列
        setShowOrHideColumn(record, kv);
    }

    /**
     * 设置是否显示隐藏列 优先级说明 参数show>参数hide>配置show>配置隐藏
     *
     * @param record record记录
     * @param kv     参数
     */
    private void setShowOrHideColumn(Record record, Kv kv) {
        //如果设置了显示列 则后续的隐藏列不用再管 显示列优先于设置隐藏
        String showColumns = kv.getStr("showColumns");
        if (StrKit.notBlank(showColumns)) {
            RecordKit.me().showColumnsForRecord(record, showColumns);
            return;
        }
        String hideColumns = kv.getStr("hideColumns");
        if (StrKit.notBlank(hideColumns)) {
            RecordKit.me().hideColumnsForRecord(record, hideColumns);
            return;
        }
        //如果参数中未配置显示，隐藏列 则查看代码中是否有配置
        showColumns = getShowColumns();
        if (StrKit.notBlank(showColumns)) {
            RecordKit.me().showColumnsForRecord(record, showColumns);
            return;
        }
        hideColumns = getHideColumns();
        if (StrKit.notBlank(hideColumns)) {
            RecordKit.me().hideColumnsForRecord(record, hideColumns);
        }
    }
}
